from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.shortcuts import render
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.settings import api_settings

from oauth.models import OAuthQQUser
from oauth.serializers import QQUserSerializer
from oauth.utils import generate_encrypted_openid


class OauthQQUrlView(APIView):
    # 路由地址： oauth/qq/authorization/
    def get(self, request):
        """点击第三方ｑｑ登录,获取ＱＱ登陆界面url地址"""

        # 获取请求的参数参数：　next    next:qq登录成功后指定跳转的页面　url的?后面的参数　
        next = request.query_params.get('next')

        # 这里的setting是django的conf自带的变量，通过它去取，达到线上跟开发用的dev配置通用
        # 就不存在只在dev中拿换到线上模式就取不出的问题
        # 获取第三方包的对象来操作
        client = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                         client_secret=settings.QQ_CLIENT_SECRET,
                         redirect_uri=settings.QQ_REDIRECT_URI,
                         state=next)
        # 通过第三方包获取qq登陆地址
        login_url = client.get_qq_url()

        return Response({'login_url': login_url})


class QQUserView(APIView):

    def get(self, request):
        """QQ认证接口: 根据code获取openid, 根据openid查询绑定的美多用户"""

        # 获取请求参数: code
        code = request.query_params.get('code')
        if not code:
            raise ValidationError({'message': '没有code参数'})

        client = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                         client_secret=settings.QQ_CLIENT_SECRET,
                         redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 根据code获取access_token
            access_token = client.get_access_token(code)

            # 根据access_token获取openid
            openid = client.get_open_id(access_token)

            # 响应数据
            # return Response({'openid': openid})
        except:
            # raise ValidationError({'message': '获取openid出错'})
            return Response({'message': '获取openid出错'}, status=500)

        # 根据openid查询绑定的美多用户
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果查询不到美多用户, 则返回openid, 等待后续用户的绑定操作
            # 调用 util.py文件里的generate_encrypted_openid方法进行加密
            # 不再明文返回 Openid, 需要先作签名加密openid, 再返回
            openid = generate_encrypted_openid(openid)
            return Response({'openid': openid})
        else:
            # todo: 生成 jwt 如果能查询到, 则生成并返回jwt, user_id, username, 完成QQ登录流程
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 生payload部分的方法
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 生成jwt的方法

            user = qquser.user  # 获取绑定的美多用户
            #  {'exp': xxx, 'email': '', 'user_id': 1, 'username': 'admin'}
            # user：登录的用户对象
            payload = jwt_payload_handler(user)  # 生成payload, 得到字典
            token = jwt_encode_handler(payload)  # 生成jwt字符串

            return Response({
                'token': token,
                'user_id': user.id,
                'username': user.username,
            })

    def post(self, request):
        # 绑定openid 和 美多用户

        # 创建序列化器
        s = QQUserSerializer(data=request.data)
        # 校验参数合法性
        s.is_valid(raise_exception=True)
        # 保存数据(绑定openid 和 美多用户, 往映射表新增一条数据)
        user = s.save()  # 返回绑定的美多用户

        # todo: 生成 jwt 如果能查询到, 则生成并返回jwt, user_id, username, 完成QQ登录流程
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 生payload部分的方法
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 生成jwt的方法

        #  {'exp': xxx, 'email': '', 'user_id': 1, 'username': 'admin'}
        # user：登录的用户对象
        payload = jwt_payload_handler(user)  # 生成payload, 得到字典
        token = jwt_encode_handler(payload)  # 生成jwt字符串

        return Response({
            'token': token,
            'user_id': user.id,
            'username': user.username,
        })

